// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license


#include "stdafx.h"
#include "GizmoManager.h"
#include "TranslationGizmo.h"
#include "ScaleGizmo.h"
#include "OrientationGizmo.h"
#include "Ui.h"

//  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

GizmoManager::GizmoManager()
: m_type(GizmoTypes::TRANSLATE),
  m_pivotId(GizmoPivotTypes::NODE),
  m_pivotNode(NULL),
  m_axesNode(NULL),
  m_view(NULL),
  m_axesType(GizmoAxesTypes::NODE)
{
}

GizmoManager::~GizmoManager()
{
    setView(NULL);
}

//  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

void GizmoManager::setView(View3d* view)
{
    if(view == m_view)
    {
        return;
    }
    // If we had a view, remove us as listeners from it
    if(m_view)
    {
        SelectionManager& selManager = m_view->getUi().getSelectionManager();
        selManager.removeSelectionChangeListener(this);
    }

    // And now register us as listeners of the new view
    if(view)
    {
        SelectionManager& selManager = view->getUi().getSelectionManager();
        selManager.addSelectionChangeListener(this);
    }
    // If the new view is NULL, get rid of the gizmo
    else
    {
        m_gizmo.reset();
    }

    m_view = view;
}

//  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

void GizmoManager::replaceGizmo(ref<Gizmo> newGizmo)
{
    // De-register current gizmo
    if(m_gizmo != NULL)
    {
        m_view->removePickable(m_gizmo);
    }

    m_gizmo = newGizmo;

    // Register this gizmo as a pickable with the view
    if(m_gizmo != NULL)
    {
        m_view->addPickable(m_gizmo);
    }
}


void GizmoManager::setGizmoType(GizmoType id)
{
    m_type = id;

    if(m_type == GizmoTypes::TRANSLATE)
    {
        replaceGizmo(makeShared<TranslationGizmo>(this));
    }
    else if(m_type == GizmoTypes::ROTATE)
    {
        replaceGizmo(makeShared<OrientationGizmo>(this));
    }
    else if(m_type == GizmoTypes::SCALE)
    {
        replaceGizmo(makeShared<ScaleGizmo>(this));
    }

    m_view->invalidate();
}


//  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

void GizmoManager::onSelectionChanged(SelectionManager * sender)
{
    Transformable* item = dynamic_cast<Transformable*>(sender->getSelection());
    m_draggedItem = item;

    if(!m_draggedItem)
    {
        replaceGizmo(ref<Gizmo>());
    }
    else
    {
        setGizmoType(m_type);
    }
}

//  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

Node* GizmoManager::getAxesNode() const
{
    ASSERT(m_axesType == GizmoAxesTypes::OTHER_NODE);
    return m_axesNode;
}

void GizmoManager::setAxesNode(Node* node)
{
    ASSERT(node != NULL);
    m_axesNode = node;

    setAxesType(GizmoAxesTypes::OTHER_NODE);
}

void GizmoManager::setAxesType(GizmoAxesType orient)
{
    ASSERT(orient >= GizmoAxesTypes::NODE
        && orient <= GizmoAxesTypes::OTHER_NODE);
    
    if(orient != GizmoAxesTypes::OTHER_NODE)
    {
        m_axesNode = NULL;
    }

    m_axesType = orient;
    m_view->invalidate();
}

GizmoAxesType GizmoManager::getAxesType() const
{
    return m_axesType;
}

